/*----------------------------------------------------------------------
 *
 * Copyright 2009, Thomas Dejanovic.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 *
 *---------------------------------------------------------------------
 *
 * Tasks to read and write bytes via the dcom uart.
 *
 *---------------------------------------------------------------------*/

`ifndef DCOM_UART_TASKS

 `define DCOM_UART_TASKS

parameter BAUD_TIME      = 8681;
parameter HALF_BAUD_TIME = 4340;


 `ifdef DCOM_GUTS

//
// bypassing UART stage and directly injecting bytes into the command
// interface.
//

task uart_send_byte;
  input [7:0] b;
  integer     usfb_i;
  begin
    @ (posedge `DCOM_GUTS.clk);
    while ((`DCOM_GUTS.clk_en === 1'd0) ||
           (`DCOM_GUTS.lpcb_if.read_p !== `DCOM_GUTS.lpcb_if.write_p))
      @ (posedge `DCOM_GUTS.clk);
    #1;
    force `DCOM_GUTS.rx_data = b;
    force `DCOM_GUTS.rx_data_valid = 1'd1;
    force `DCOM_GUTS.rx_error = 1'd0;
    @ (posedge `DCOM_GUTS.clk);
    #1;
    release `DCOM_GUTS.rx_data;
    release `DCOM_GUTS.rx_data_valid;
    release `DCOM_GUTS.rx_error;
    for (usfb_i=0 ; usfb_i < 4; usfb_i=usfb_i+1) @ (posedge `DCOM_GUTS.clk);
  end
endtask // uart_send_byte

task uart_get_byte;
  output [7:0] b;
  integer      ugfb_i;
  begin
    @ (posedge `DCOM_GUTS.clk);
    while ((`DCOM_GUTS.clk_en === 1'd0) ||
           (`DCOM_GUTS.lpcb_if.read_p !== `DCOM_GUTS.lpcb_if.write_p))
      @ (posedge `DCOM_GUTS.clk);
    #1;
    force `DCOM_GUTS.tx_ready = 1'd1;
    while (`DCOM_GUTS.tx_data_valid === 1'd0) @ (posedge `DCOM_GUTS.clk);
    b = `DCOM_GUTS.tx_data;
    #1;
    force `DCOM_GUTS.tx_ready = 1'd0;
    while (`DCOM_GUTS.tx_data_valid === 1'd1) @ (posedge `DCOM_GUTS.clk);
    #1;
    release `DCOM_GUTS.tx_ready;
  end
endtask // uart_get_fast_byte

 `else // !`ifdef DCOM_GUTS

task uart_send_byte;
  input [7:0] b;
  integer     usb_i;
  reg         usb_tick, usb_start_tick, usb_stop_tick;
  begin
    // start bit.
    txd_in = 1'd0;
    usb_tick = 1'd0;
    usb_start_tick = 1'd1;
    usb_stop_tick  = 1'd0;
    #BAUD_TIME;
    usb_tick = 1'd1;
    usb_start_tick = 1'd0;
    // send byte.
    for (usb_i=0 ; usb_i < 8; usb_i=usb_i+1) begin
      txd_in = b[usb_i];
      #BAUD_TIME;
      usb_tick = ~usb_tick;
    end
    // stop bit.
    txd_in = 1'd1;
    usb_stop_tick  = 1'd1;
    #BAUD_TIME;
    usb_tick = ~usb_tick;
    usb_stop_tick  = 1'd0;
  end
endtask // uart_send_byte

task uart_get_byte;
  output [7:0] b;
  integer      ugb_i;
  reg          ugb_tick, ugb_start_tick, ugb_stop_tick;
  begin
    ugb_tick = 1'd0;
    ugb_start_tick = 1'd0;
    ugb_stop_tick  = 1'd0;
    // look for start bit.
    // while (rxd_out === 1'd0) @ (rxd_out);
    while (rxd_out === 1'd1) @ (rxd_out);

    // this should be a start bit.
    ugb_start_tick = 1'd1;

    #HALF_BAUD_TIME;
    for (ugb_i=0 ; ugb_i < 8; ugb_i=ugb_i+1) begin
      ugb_tick = ~ugb_tick;
      #BAUD_TIME;
      ugb_start_tick = 1'd0;
      b[ugb_i] = rxd_out;
    end

    ugb_stop_tick  = 1'd1;

    #HALF_BAUD_TIME;
    // stop bit?
    if (rxd_out !== 1'd1)
      $display("// uart_get_byte didn't find stop bit at time %t", $time);
  end
endtask // uart_get_byte

 `endif

`endif //  `ifndef DCOM_UART_TASKS

/*----------------------------------------------------------------*/

// Local Variables:
// mode: verilog
// End:
